package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.domain.AccountLog;
import cn.wolfcode.domain.AccountTransaction;
import cn.wolfcode.domain.OperateIntergralVo;
import cn.wolfcode.mapper.AccountLogMapper;
import cn.wolfcode.mapper.AccountTransactionMapper;
import cn.wolfcode.mapper.UsableIntegralMapper;
import cn.wolfcode.service.IUsableIntegralService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.msg.IntergralCodeMsg;
import com.alibaba.fastjson.JSON;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.BusinessActionContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.IdGenerator;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;


/**
 * @author BAI
 */
@Service
@Slf4j
public class UsableIntegralServiceImpl implements IUsableIntegralService {
    @Autowired
    private UsableIntegralMapper usableIntegralMapper;
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;
    @Autowired
    private AccountLogMapper accountLogMapper;


    @Override
    public String tryIntegralPay(BusinessActionContext actionContext,@BusinessActionContextParameter(paramName = "vo") OperateIntergralVo vo) {
        log.info("[积分支付] try方法,参数:{}", JSON.toJSONString(vo));
        // 1.先冻结积分
        int row = usableIntegralMapper.freezeIntergral(vo.getUserId(), vo.getValue());
        // 2.判断是否冻结成功
        if (row <= 0) {
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
        // 3.生成交易流水记录号
        String tradeNo = buildTradeNo();
        BusinessActionContextUtil.addContext("tradeNo",tradeNo);
        return tradeNo;
    }

    @Override
    public void commitIntegralPay(BusinessActionContext actionContext) {
        log.info("[积分支付] commit方法,参数:{}", JSON.toJSONString(actionContext.getActionContext()));
        // 1.支付冻结金额
        OperateIntergralVo vo = actionContext.getActionContext("vo", OperateIntergralVo.class);
        if (vo != null) {
            usableIntegralMapper.commitChange(vo.getUserId(), vo.getValue());
            // 2.生成交易流水记录
            AccountLog accountLog = buildAccontLog(vo, AccountLog.TYPE_DECR, actionContext.getActionContext("tradeNo",String.class));
        }
    }

    @Override
    public void rollbackIntegralPay(BusinessActionContext actionContext) {
        log.info("[积分支付] rollback方法,参数:{}", JSON.toJSONString(actionContext.getActionContext()));
        // 1.取消冻结金额
        OperateIntergralVo vo = actionContext.getActionContext("vo", OperateIntergralVo.class);
        if (vo != null) {
            usableIntegralMapper.unFreezeIntergral(vo.getUserId(), vo.getValue());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String integralPay(OperateIntergralVo vo) {
        // 1.先扣减积分
        int row = usableIntegralMapper.decrIntegral(vo.getUserId(), vo.getValue());
        // 2.判断是否扣减成功
        if (row <= 0) {
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
        AccountLog accountLog = buildAccontLog(vo,AccountLog.TYPE_DECR,buildTradeNo());
        // 4.生成交易记录
        return accountLog.getTradeNo();
    }


    private String buildTradeNo() {
        String prefix = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        return prefix + IdGenerateUtil.get().nextId();
    }

    private AccountLog buildAccontLog(OperateIntergralVo vo,Integer type,String tradeNo) {
        // 3.成功,生成交易流水记录
        AccountLog accountLog = new AccountLog();
        accountLog.setAmount(vo.getValue());
        accountLog.setInfo(vo.getInfo());
        accountLog.setTradeNo(tradeNo);
        accountLog.setGmtTime(new Date());
        accountLog.setType(type);
        accountLog.setOutTradeNo(vo.getPk());
        accountLogMapper.insert(accountLog);
        return accountLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void integralRefund(OperateIntergralVo vo) {
        // 1.查询交易流水记录
        AccountLog accountLog = accountLogMapper.selectByTradeNoAndTpe(vo.getPk(),AccountLog.TYPE_DECR);
        // 2.判断是否存在
        if (accountLog == null) {
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        // 3.增加记录
        AccountLog accountLog1 = buildAccontLog(vo, AccountLog.TYPE_INCR, accountLog.getTradeNo());
        // 4.增加积分
        usableIntegralMapper.addIntergral(vo.getUserId(), vo.getValue());

    }
}
